import utils from './utils';

/**
 * 该函数用于调整元素位置和尺寸，确保其在可视区域内可见。通过动态调整元素坐标和尺寸，解决元素超出浏览器视口的问题。
 * 注意：调整大小时，只会在超出时缩小，不会放大。位置调整会尽可能将元素移入可视区域，但不会改变大小（除非配置了调整大小）。
 * 
 * @param  elFuturePos: 元素未来的位置（包含 left 和 top 属性）
 * @param  elRegion: 元素的区域信息（包含 width 和 height）
 * @param  visibleRect: 可视区域的信息（包含 left, top, right, bottom）
 * @param  overflow: 一个配置对象，包含四个属性：adjustX, adjustY, resizeWidth, resizeHeight，用于控制调整行为
 * @return {left, top, width, height} - 调整后的X坐标,y坐标,宽度,高度
 */
function adjustForViewport(elFuturePos, elRegion, visibleRect, overflow) {
  // 首先克隆 elFuturePos 到 pos，避免修改原对象。
  const pos = utils.clone(elFuturePos);
  // 从 elRegion 中提取 width 和 height 作为初始的 size。
  const size = {
    width: elRegion.width,
    height: elRegion.height,
  };

  // 根据 overflow 的配置和元素与可视区域的位置关系，进行一系列调整。

  // 调整分为水平方向（X轴）和垂直方向（Y轴），每个方向有三种情况：
  // 水平方向（X轴）：
  // a. 如果元素左边界超出可视区域左边界，且 overflow.adjustX 为 true，则将左边界调整到可视区域左边界。
  if (overflow.adjustX && pos.left < visibleRect.left) {
    pos.left = visibleRect.left;
  }

  // Left edge inside and right edge outside viewport, try to resize it.
  // b. 如果元素左边界在可视区域内，但右边界超出可视区域右边界，且 overflow.resizeWidth 为 true，则尝试缩小宽度（使右边界不超出）。
  if (
    overflow.resizeWidth &&
    pos.left >= visibleRect.left &&
    pos.left + size.width > visibleRect.right
  ) {
    size.width -= pos.left + size.width - visibleRect.right;
  }

  // Right edge outside viewport, try to move it.
  // c. 如果元素右边界超出可视区域右边界，且 overflow.adjustX 为 true，则尝试将元素向左移动（移动后保证左边界不超出可视区域左边界，即取Math.max(visibleRect.right - size.width, visibleRect.left)）。
  if (overflow.adjustX && pos.left + size.width > visibleRect.right) {
    // 保证左边界和可视区域左边界对齐
    pos.left = Math.max(visibleRect.right - size.width, visibleRect.left);
  }

  // 垂直方向（Y轴）：
  // Top edge outside viewport, try to move it.
  // a. 如果元素上边界超出可视区域上边界，且 overflow.adjustY 为 true，则将上边界调整到可视区域上边界。
  if (overflow.adjustY && pos.top < visibleRect.top) {
    pos.top = visibleRect.top;
  }

  // Top edge inside and bottom edge outside viewport, try to resize it.
  // b. 如果元素上边界在可视区域内，但下边界超出可视区域下边界，且 overflow.resizeHeight 为 true，则尝试缩小高度（使下边界不超出）。
  if (
    overflow.resizeHeight &&
    pos.top >= visibleRect.top &&
    pos.top + size.height > visibleRect.bottom
  ) {
    size.height -= pos.top + size.height - visibleRect.bottom;
  }

  // Bottom edge outside viewport, try to move it.
  // c. 如果元素下边界超出可视区域下边界，且 overflow.adjustY 为 true，则尝试将元素向上移动（移动后保证上边界不超出可视区域上边界，即取Math.max(visibleRect.bottom - size.height, visibleRect.top)）。
  if (overflow.adjustY && pos.top + size.height > visibleRect.bottom) {
    // 保证上边界和可视区域上边界对齐
    pos.top = Math.max(visibleRect.bottom - size.height, visibleRect.top);
  }

  // 函数返回一个合并了调整后的位置（pos）和尺寸（size）的对象
  return utils.mix(pos, size);
}

export default adjustForViewport;
